package com.richard.library.basic.util;

import android.annotation.SuppressLint;
import android.text.InputType;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.TextView;

/**
 * <pre>
 * Description : 扫码枪扫码处理
 * Author : admin-richard
 * Date : 2019-12-01 21:33
 * Changelog:
 * Version            Date            Author              Detail
 * ----------------------------------------------------------------------
 * 1.0         2019-12-01 21:33     admin-richard         new file.
 * </pre>
 */
public final class ScanCodeUtil {

    private static long lastClickTime;


    /**
     * 监听扫码事件
     *
     * @param editText            监听控件
     * @param isAutoClearValue    是否自动清空EditText获取的值
     * @param isClickShowKeyboard 必填 点击editText是否允许弹出系统输入软键盘
     * @param isScanCodePay       是否为扫码支付操作
     */
    @SuppressLint("ClickableViewAccessibility")
    public static void monitorScanCode(
            EditText editText
            , boolean isAutoClearValue
            , boolean isScanCodePay
            , boolean isClickShowKeyboard
            , boolean isAutoRegainFocus
    ) {
        monitorScanCode(editText, isAutoClearValue, isScanCodePay, isAutoRegainFocus, isClickShowKeyboard, null);
    }

    /**
     * 监听扫码事件
     *
     * @param editText            监听控件
     * @param isAutoClearValue    是否自动清空EditText获取的值
     * @param isClickShowKeyboard 必填 点击editText是否允许弹出系统输入软键盘
     * @param isScanCodePay       是否为扫码支付操作
     */
    @SuppressLint("ClickableViewAccessibility")
    public static void monitorScanCode(
            EditText editText
            , boolean isAutoClearValue
            , boolean isScanCodePay
            , boolean isClickShowKeyboard
            , ScanCodeResult scanCodeResult
    ) {
        monitorScanCode(editText, isAutoClearValue, isScanCodePay, false, isClickShowKeyboard, scanCodeResult);
    }

    /**
     * 监听扫码事件
     *
     * @param editText            必填 监听控件
     * @param isAutoClearValue    必填 是否自动清空EditText获取的值
     * @param isScanCodePay       必填 是否为扫码支付操作
     * @param isAutoRegainFocus   必填 是否自动重新获取焦点(若isAutoRegainFocus = true,则scanCodeResult.isAutoRegainFocus()条件将会被忽略,为false时则会已scanCodeResult.isAutoRegainFocus()为准)
     * @param isClickShowKeyboard 必填 点击editText是否允许弹出系统输入软键盘
     * @param scanCodeResult      选填 扫码结果回调
     */
    @SuppressLint("ClickableViewAccessibility")
    private static void monitorScanCode(
            EditText editText
            , boolean isAutoClearValue
            , boolean isScanCodePay
            , boolean isAutoRegainFocus
            , boolean isClickShowKeyboard
            , ScanCodeResult scanCodeResult
    ) {
        //设置为TYPE_NULL，不允许弹出系统软键盘，以防有些扫码枪扫出来的码顺序不一致的问题
        editText.setInputType(InputType.TYPE_NULL);
        editText.setFocusable(true);
        editText.setSingleLine(true);
        editText.setSelection(editText.length());
        editText.setImeOptions(EditorInfo.IME_ACTION_SEARCH);

        //获取焦点
        if((isAutoRegainFocus || (scanCodeResult != null && scanCodeResult.isAutoRegainFocus())) && !editText.isFocused()){
            editText.requestFocus();
        }

        //监听点击事件
        if (isClickShowKeyboard) {
            editText.setOnTouchListener((v, event) -> {
                if (event.getAction() == MotionEvent.ACTION_UP) {
                    KeyboardUtil.showSoftInput(editText);
                    return false;
                }
                return false;
            });
        }

        //监听编辑事件
        editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                KeyboardUtil.hideSoftInput(v);

                if(scanCodeResult != null && !scanCodeResult.isCanReceiveScanCode()){
                    editText.setText("");
                    return true;
                }

                String code = v.getText().toString().trim();
                if(TextUtils.isEmpty(code)){
                    return true;
                }

                if (isAutoClearValue) {
                    editText.setText("");
                }

                if (isScanCodePay && fastClickCheck(2000)) {
                    return true;
                }

                if (code.endsWith("\n")) {
                    code = code.substring(0, code.length() - 1);
                }

                if (scanCodeResult != null) {
                    scanCodeResult.onScanCodeSuccess(code);
                }
                return true;
            }
        });

        //搜索框焦点变化事件
        editText.setOnFocusChangeListener((v, hasFocus) -> {
            if (hasFocus) {
                return;
            }

            if (scanCodeResult != null && !scanCodeResult.isAutoRegainFocus()) {
                return;
            }

            if (scanCodeResult == null && !isAutoRegainFocus) {
                return;
            }

            editText.postDelayed(() -> {
                if (scanCodeResult == null || scanCodeResult.isShowToUser()) {
                    editText.setFocusable(true);
                    editText.setFocusableInTouchMode(true);
                    editText.requestFocus();
                }
            }, 1);
        });
    }

    /**
     * 验证是否为快速点击
     * @param millisecond 多少毫秒内算快速点击
     * @return true:快速点击,false:慢速点击
     */
    private static boolean fastClickCheck(long millisecond) {
        boolean flag = true;
        long currentClickTime = System.currentTimeMillis();
        if ((currentClickTime - lastClickTime) >= millisecond) {
            flag = false;
        }
        lastClickTime = currentClickTime;
        return flag;
    }

    public interface ScanCodeResult {

        /**
         * 扫码界面对于用户是否是可见的
         */
        default boolean isShowToUser() {
            return true;
        }

        /**
         * 扫码框是否可以自动再次重新获取焦点
         */
        default boolean isAutoRegainFocus() {
            return false;
        }

        /**
         * 是否可以接收扫码
         */
        default boolean isCanReceiveScanCode(){
            return true;
        }

        /**
         * 当扫码成功时回调
         *
         * @param code 扫入的码
         */
        void onScanCodeSuccess(String code);
    }

}
